﻿using Apewer;
using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace Apewer.Internals
{

    internal class HashHelper
    {

        /// <summary>获取 MD5 值。</summary>
        public static byte[] MD5(params byte[] argBytes)
        {
            var result = Constant.EmptyBytes;
            try
            {
                var csp = new MD5CryptoServiceProvider();
                result = csp.ComputeHash(argBytes);
                csp.Clear();
#if !NET20
                csp.Dispose();
#endif
            }
            finally { }
            return result;
        }

        /// <summary>获取 MD5 值。</summary>
        public static byte[] MD5(Stream argStream)
        {
            var result = Constant.EmptyBytes;
            try
            {
                var csp = new MD5CryptoServiceProvider();
                result = csp.ComputeHash(argStream);
                csp.Clear();
#if !NET20
                csp.Dispose();
#endif
            }
            finally { }
            return result;
        }

        /// <summary>获取 MD5 值。</summary>
        public static byte[] MD5(Stream argStream, Action<Int64> argProgressed, object argSender)
        {
            var origin = argStream;
            var validtotal = true;

            // 总长度。
            var total = 0L;
            try { total = origin.Length; } catch { validtotal = false; }
            if (origin.Length <= 0) validtotal = false;
            if (validtotal == false) return Constant.EmptyBytes;

            // 初始化。
            var validcallback = argProgressed != null;
            var capacity = (long)Constant.DefaultBufferCapacity;
            var buffer = new byte[capacity];
            var md5 = new MD5CryptoServiceProvider();
            md5.Initialize();

            // 读取。
            var offset = 0L;
            var failed = false;
            var final = false;
            while (offset < origin.Length)
            {
                var current = capacity;
                if (offset + current > total)
                {
                    current = total - offset;
                    final = true;
                }
                try
                {
                    origin.Read(buffer, 0, Convert.ToInt32(current));
                }
                catch
                {
                    failed = true;
                    break;
                }

                if (final)
                {
                    md5.TransformFinalBlock(buffer, 0, Convert.ToInt32(current));
                }
                else
                {
                    md5.TransformBlock(buffer, 0, Convert.ToInt32(current), buffer, 0);
                }

                offset += capacity;
            }

            if (failed)
            {
                md5.Clear();
#if !NET20
                md5.Dispose();
#endif
                return Constant.EmptyBytes;
            }
            else
            {
                var result = md5.Hash;
                md5.Clear();
#if !NET20
                md5.Dispose();
#endif
                return result;
            }
        }

        /// <summary>获取 SHA1 值。</summary>
        public static byte[] SHA1(params byte[] argBytes)
        {
            var result = Constant.EmptyBytes;
            try
            {
                var csp = new SHA1CryptoServiceProvider();
                result = csp.ComputeHash(argBytes);
                csp.Clear();
#if !NET20
                csp.Dispose();
#endif
            }
            finally { }
            return result;
        }

        /// <summary>获取 SHA1 值。</summary>
        public static byte[] SHA1(Stream argStream)
        {
            var result = Constant.EmptyBytes;
            try
            {
                var csp = new SHA1CryptoServiceProvider();
                result = csp.ComputeHash(argStream);
                csp.Clear();
#if !NET20
                csp.Dispose();
#endif
            }
            finally { }
            return result;
        }

#if !NET20

        /// <summary>获取 SHA256 值。</summary>
        public static byte[] SHA256(params byte[] argBytes)
        {
            var result = Constant.EmptyBytes;
            try
            {
                var csp = new SHA256CryptoServiceProvider();
                result = csp.ComputeHash(argBytes);
                csp.Clear();
                csp.Dispose();
            }
            finally { }
            return result;
        }

        /// <summary>获取 SHA256 值。</summary>
        public static byte[] SHA256(Stream argStream)
        {
            var result = Constant.EmptyBytes;
            try
            {
                var csp = new SHA256CryptoServiceProvider();
                result = csp.ComputeHash(argStream);
                csp.Clear();
                csp.Dispose();
            }
            finally { }
            return result;
        }

#endif

    }

}
